﻿import '@/assets/icons';
import axios from 'axios';
import {attrSeparator, sleep} from '@/utils/common_utils';
import Vue, {VNode} from 'vue';
import Toast from '@/components/common/Toast.vue';

class BaseComponentStaticData {
  public readonly window = window;
  public readonly axios = axios;
  public readonly attrSeparator = attrSeparator;
  public windowName = window.name;
  public $toast: Toast['utilType'] = null;

  public readonly inputAttrs = {
    autocomplete: 'off',
    autocapitalize: 'off',
    autocorrect: 'off',
    spellcheck: 'false'
  };
}

/**
 * 组件基类
 */
class BaseComponent extends Vue {
  private static readonly staticData = Vue.observable(new BaseComponentStaticData());

  static {
    Object.defineProperty(window, 'name', {
      get: () => this.staticData.windowName,
      set: v => this.staticData.windowName = v
    });
    const properties = Object.getOwnPropertyDescriptors(this.staticData);
    Object.defineProperties(this.prototype, properties);
  }

  private _abortSignal: AbortSignal = null;

  public get abortSignal() {
    return this._abortSignal ??= (() => {
      const abortController = new AbortController();
      this.$once('hook:beforeDestroy', () => abortController.abort());
      return abortController.signal;
    })();
  }

  public $sleep(timeout: number) {
    return sleep(timeout);
  }
}

interface BaseComponent extends BaseComponentStaticData {
  beforeCreate(): void;
  created(): void;
  beforeMount(): void;
  mounted(): void;
  beforeDestroy(): void;
  destroyed(): void;
  render(): VNode;
}

export default BaseComponent;
